// Kony

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemInterface.h"
#include "GameFramework/Character.h"
#include "Interaction/CombatInterface.h"
#include "AbilitySystem/Data/CharacterClassInfo.h"
#include "BaseCharacter.generated.h"


class UAbilitySystemComponent;
class UAttributeSet;
class UGameplayEffect;
class UGameplayAbility;
class UAnimMontage;
class UMaterialInstance;
class UWidgetComponent;
class UDebuffNiagaraComponent;
class UTargetLockComponent;
class UPassiveNiagaraComponent;
class USphereComponent;


/**
 * 所有角色基础类
 */
UCLASS(Abstract)
class GASC_HUANLING_API ABaseCharacter : public ACharacter, public IAbilitySystemInterface , public ICombatInterface
{
	GENERATED_BODY()

public:
	ABaseCharacter();
	virtual void Tick(float DeltaTime) override;
	//用于服务器复制数据的函数
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
	UAttributeSet* GetAttributeSet() const{return AttributeSet;} //返回属性集
	//多播广播处理死亡事件 用于服务端和客户端处理
	UFUNCTION(NetMulticast, Reliable)
	virtual void MulticastHandleDeath(const FVector& DeathImpulse);
	//受到伤害
	virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, AActor* DamageCauser) override;
	//敌人死亡后尸体生命周期
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Combat")
	float LifeSpan = 5.f;
	//玩家是攻击锁定目标，怪物是正在攻击的目标
	UPROPERTY(BlueprintReadWrite, Category="Combat")
	TObjectPtr<AActor> CombatTarget;
	//蒙太奇攻击动画数组，用于获取攻击动画，可以用来做连续攻击或者左右手攻击动画的 顺序|随机播放
	UPROPERTY(EditAnywhere, Category="Combat")
	TArray<FTaggedMontage> AttackMontages;

	/** Combat Interface 战斗接口 */
	//重写获取武器插槽位置
	virtual FVector GetCombatSocketLocation_Implementation(const FGameplayTag& MontageTag, bool bUseFacing = false, float FacingDistance = 150.0f) override;
	//重写战斗接口的受击反应函数
	virtual UAnimMontage* GetHitReactMontage_Implementation() override;
	//濒死函数
	virtual void Die(const FVector& DeathImpulse) override;
	//重写获取是否死亡
	virtual bool IsDead_Implementation() const override;
	//重写获取化身
	virtual AActor* GetAvatar_Implementation() override;
	//重写获取战斗蒙太奇数组
	virtual TArray<FTaggedMontage> GetAttackMontages_Implementation() override;
	//重写获取受击出血效果
	virtual UNiagaraSystem* GetHitBloodEffect_Implementation() override;
	//重写通过标签TAG返回TaggedMontage结构体
	virtual FTaggedMontage GetTaggedMontageByTag_Implementation(const FGameplayTag& MontageTag) override;
	//重写获取召唤随从数量
	virtual int32 GetMinionCount_Implementation() override;
	//重写写入当前召唤随从数量 传入正就是递增，传入负就是递减
	virtual void IncremenetMinionCount_Implementation(int32 Amount) override;
	//重写获取怪物职业
	virtual ECharacterClass GetCharacterClass_Implementation() override;
	//重写显示目标锁定光圈
	virtual void ShowTargetIndicator_Implementation() override;
	//重写隐藏目标锁定光圈
	virtual void HideTargetIndicator_Implementation() override;
	//重写获取能力系统组件生效时广播委托 广播类型必须带上 & 否则无法生效
	virtual FOnASCRegistered& GetOnASCRegisteredDelegate() override;
	//重写获取死亡委托
	virtual FOnDeathSignature& GetOnDeathDelegate() override;
	//重写受到伤害委托
	virtual FOnDamageSignature& GetOnDamageSignature() override;
	//重写获取插槽组件函数,用于获取武器插槽等 角色身上的插槽
	virtual USkeletalMeshComponent* GetSocketComponent_Implementation(const FString& SocketName) override;
	//重写设置持续施法
	virtual void SetIsBeingShocked_Implementation(bool bInShock) override;
	//重写是否正在持续被电击
	virtual bool IsBeingShocked_Implementation() const override;
	/** end Combat Interface */
	//获取能力系统组件生效时广播委托
	FOnASCRegistered OnAscRegistered;
	//获取死亡委托
	FOnDeathSignature OnDeathDelegate;
	//受到伤害委托（这个并不是直接计算伤害的，而是用于系统的计算径向衰减伤害传递的）
	FOnDamageSignature OnDamageDelegate;
	
	//是否燃烧 ReplicatedUsing 用于复制给客户端通知，虽然燃烧不需要执行角色动画，但可以利用这个变量 通知客户端显示和取消燃烧效果
	UPROPERTY(ReplicatedUsing = OnRep_Burned, BlueprintReadOnly)
	bool bIsBurn = false;
	//是否眩晕 ReplicatedUsing 用于复制给客户端通知
	UPROPERTY(ReplicatedUsing = OnRep_Stunned, BlueprintReadOnly)
	bool bIsStunned = false;
	//是否击倒
	UPROPERTY(ReplicatedUsing = OnRep_Downed, BlueprintReadOnly)
	bool bIsDown = false;
	//是否蹲伏
	UPROPERTY(ReplicatedUsing = OnRep_Crouching, BlueprintReadOnly)
	bool bIsCrouching = false;

	//处于被持续电击
	UPROPERTY(Replicated, BlueprintReadOnly)
	bool bIsBeingShocked = false;

	UFUNCTION()
	virtual void OnRep_Burned();
	UFUNCTION()
	virtual void OnRep_Stunned();
	UFUNCTION()
	virtual void OnRep_Downed();
	UFUNCTION()
	virtual void OnRep_Crouching();
	
protected:
	virtual void BeginPlay() override;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat")
	TObjectPtr<USkeletalMeshComponent> Weapon;
	//武器插槽名称，用于释放法术等
	UPROPERTY(EditAnywhere, Category="Combat")
	FName WeaponTipSocketName;
	//怪物的左右手插槽
	UPROPERTY(EditAnywhere, Category="Combat")
	FName LeftHandSocketName;
	UPROPERTY(EditAnywhere, Category="Combat")
	FName RightHandSocketName;
	//怪物的尾巴插槽
	UPROPERTY(EditAnywhere, Category="Combat")
	FName TailSocketName;
	//是否死亡变量
	UPROPERTY(BlueprintReadOnly)
	bool bDead = false;
	//判断如果为0则不需要受击反应
	UPROPERTY(BlueprintReadOnly, Category = "Combat")
	bool bHitRectiong = false;
	//基础移动速度
	UPROPERTY(EditAnywhere, Category = "Combat")
	float BaseWalkSpeed = 400.f;
	
	//眩晕标签更变函数
	virtual void StunTagChanged(const FGameplayTag CallbackTag, int32 NewCount);
	//击倒标签更变函数
	virtual void DownTagChanged(const FGameplayTag CallbackTag, int32 NewCount);
	//蹲伏标签更变函数
	virtual void CrouchTagChanged(const FGameplayTag CallbackTag, int32 NewCount);
	
	
	UPROPERTY()
	TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
	UPROPERTY()
	TObjectPtr<UAttributeSet> AttributeSet;
	//初始化能力系统虚函数，玩家角色和怪物角色可以继承后 来调用能力系统AbilitySystemComponent接口
	//来初始化 执行一些能力效果操作
	virtual void InitAbilityActorInfo();
	
	//默认主要属性集函数 ，玩家角色和怪物角色可以继承后 来调用属性集AttributeSet接口
	UPROPERTY(BlueprintReadOnly,EditAnywhere, Category="Attributes")
	TSubclassOf<UGameplayEffect> DefaultPrimaryAttributes;
	//初始化默认次要属性
	UPROPERTY(BlueprintReadOnly,EditAnywhere, Category="Attributes")
	TSubclassOf<UGameplayEffect> DefaultSecondaryAttributes;
	//初始化默认生命值 法力 等核心属性
	UPROPERTY(BlueprintReadOnly,EditAnywhere, Category="Attributes")
	TSubclassOf<UGameplayEffect> DefaultVitalAttributes;
	//应用效果到游戏角色 主要是绑定游戏能力和属性集 通用类
	void ApplyEffectToSelf(TSubclassOf<UGameplayEffect> GameplayEffectClass,float level) const;
	//初始化默认属性集 包含主属性和次要属性
	virtual void InitializeDefaultAttributes() const;
	//头顶血条
	UPROPERTY(VisibleAnywhere,BlueprintReadOnly)
	TObjectPtr<UWidgetComponent> HealthBar;
	//添加角色能力
	void AddCharacterAbilities();
	
	/* 死亡后溶解效果  start */
	//溶解效果函数
	void Dissolve();
	//蓝图实现开始时间轴
	UFUNCTION(BlueprintImplementableEvent)
	void StartDissolveTimeline(UMaterialInstanceDynamic* DynamicMaterialInstance);
	UFUNCTION(BlueprintImplementableEvent)
	void StartWeaponDissolveTimeline(UMaterialInstanceDynamic* DynamicMaterialInstance);
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<UMaterialInstance> DissolveMaterialInstance;
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	TObjectPtr<UMaterialInstance> WeaponDissolveMaterialInstance;
	/* 死亡后溶解效果  end */
	
	//受击出血效果
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat")
	UNiagaraSystem* HitBloodEffect;
	//死亡音效
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Combat")
	USoundBase* DeathSound = nullptr;

	/* 随从 */
	int32 MinionCount = 0;

	//设置敌人职业 默认战士，从敌人类移动过来的,也可以用于玩家 ，不过暂时没啥用，以后可以拓展成玩家和怪物都有相同的职业
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Character Class Defaults")
	ECharacterClass CharacterClass = ECharacterClass::Warrior;

	//选择目标特效
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Combat")
	TObjectPtr<UTargetLockComponent> TargetLockComponent;
	//异常粒子效果组件 - 燃烧
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<UDebuffNiagaraComponent> BurnDebuffComponent;
	//异常粒子效果组件 - 眩晕
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<UDebuffNiagaraComponent> StunDebuffComponent;
	//探查球体组件
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Detection")
	TObjectPtr<USphereComponent> DetectionSphere;
	
	
private:
	//启动能力数组
	UPROPERTY(EditAnywhere, Category="Abilities")
	TArray<TSubclassOf<UGameplayAbility>> StartupAbilities;
	//被动能力数组
	UPROPERTY(EditAnywhere, Category="Abilities")
	TArray<TSubclassOf<UGameplayAbility>> StartupPassiveAbilities;

	//受击反应动画蒙太奇
	UPROPERTY(EditAnywhere, Category="Combat")
	TObjectPtr<UAnimMontage> HitReactMontage;

	/* 被动粒子组件部分 */
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<UPassiveNiagaraComponent> HaloOfProtectionNiagaraComponent; //光环护盾
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<UPassiveNiagaraComponent> LifeSiphonNiagaraComponent; //生命汲取
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<UPassiveNiagaraComponent> ManaSiphonNiagaraComponent; //法力汲取

	//用于装载效果粒子组件的场景组件
	UPROPERTY(VisibleAnywhere)
	TObjectPtr<USceneComponent> EffectAttachComponent;
};
